from rest_framework import viewsets, mixins, exceptions
from rest_framework.decorators import action
from django.conf import settings

from connection.models import Connection, ConnectionState
from connection.serializers import ConnectionSerializer
from connection.services import connection_service
from libs.decorators import required_data_fields
from libs.simple_responses import api_success, api_created_success
from libs.auth.openapi import openapi_auth
from task.services import schedule_service
from libs.enums import SystemAppKey, LogModule
from system.services import organization_service, encrypt_service
from log.services import log_service


class ConnectionOpenAPI(viewsets.GenericViewSet, mixins.CreateModelMixin):
    queryset = Connection.objects.all()
    serializer_class = ConnectionSerializer
    ordering_fields = ('id',)
    authentication_classes = []
    permission_classes = []

    def get_instance(self, thirdparty_id):
        instance = connection_service.get_connection_by_thirdparty_id(self.request.connection.partner_id, thirdparty_id)
        if not instance:
            raise exceptions.ValidationError('无效id')
        return instance

    @openapi_auth()
    @required_data_fields(['connection_id', 'organization'])
    def create(self, request, *args, **kwargs):
        thirdparty_id = request.data.get('connection_id')
        if connection_service.exists_thirdparty_id(request.connection.partner_id, thirdparty_id):
            raise exceptions.ValidationError('重复数据')
        organization_name = request.data.get('organization')
        partner = connection_service.get_or_create_org_partner(organization_name)
        connection = connection_service.create_connection(
            partner=partner,
            state=ConnectionState.DRAFT.value,
            start_time=request.data.get('start_time'),
            end_time=request.data.get('end_time'),
            thirdparty_app=request.connection.partner,
            thirdparty_id=thirdparty_id
        )
        data = ConnectionSerializer(connection).data
        return api_created_success(data=data)

    @openapi_auth()
    @required_data_fields(['connection_id'])
    @action(methods=['post'], detail=False, url_path='update')
    def update_info(self, request, *args, **kwargs):
        thirdparty_id = request.data.get('connection_id')
        start_time = request.data.get('start_time')
        end_time = request.data.get('end_time')
        instance = self.get_instance(thirdparty_id)
        instance.start_time = start_time
        instance.end_time = end_time
        instance.save()
        return api_success(data={})

    @openapi_auth()
    @required_data_fields(['connection_id'])
    @action(methods=['post'], detail=False, url_path='rejected-callback')
    def rejected_callback(self, request, *args, **kwargs):
        thirdparty_id = request.data.get('connection_id')
        instance = self.get_instance(thirdparty_id)
        instance.state = ConnectionState.REJECTED.value
        instance.save()
        return api_success(data={})

    @openapi_auth()
    @required_data_fields(['connection_id', 'certificate_url'])
    @action(methods=['post'], detail=False, url_path='signed-callback')
    def signed_callback(self, request, *args, **kwargs):
        thirdparty_id = request.data.get('connection_id')
        instance = self.get_instance(thirdparty_id)
        certificate_url = request.data.get('certificate_url')
        connection_service.import_certificate(instance, certificate_url)
        instance.state = ConnectionState.ONGOING.value
        instance.save()
        schedule_service.connection_created(instance)
        return api_success({})

    @openapi_auth()
    @required_data_fields(['connection_id'])
    @action(methods=['post'], detail=False, url_path='generate-certificate-page')
    def get_generate_certificate_page(self, request, *args, **kwargs):
        thirdparty_id = request.data.get('connection_id')
        url = f'{settings.WEBSITE_URL}/#/connection/index?thirdparty_app={request.connection.partner_id}&thirdparty_id={thirdparty_id}'
        return api_success(data={'url': url})

    @openapi_auth()
    @required_data_fields(['certificate_url'])
    @action(methods=['post'], detail=False, url_path='certificates/import')
    def import_certificate(self, request, *args, **kwargs):
        certificate_url = request.data.get('certificate_url')
        if request.connection.partner.system_app_key == SystemAppKey.WWEXX.value:
            open_id = request.data.get('open_id')
            filing_file_url = request.data.get('filing_file_url')
            system_organization = organization_service.get()
            system_organization.filings_id = open_id
            system_organization.save()
            encrypt_service.set_public_key_verify_url(filing_file_url)
        connection_service.import_certificate(request.connection, certificate_url)
        partner = request.connection.partner
        log_service.build_update_log(None, request.connection, module=LogModule.APP_CONNECTION.value, content=f'导入了授权书, 合作方：[{partner.name}]')
        return api_success(data={})
